package com.ruoyi.law.controller;


import cn.felord.payment.wechat.enumeration.TradeState;
import cn.felord.payment.wechat.v3.WechatApiProvider;
import cn.felord.payment.wechat.v3.WechatBatchTransferApi;
import cn.felord.payment.wechat.v3.WechatResponseEntity;
import cn.felord.payment.wechat.v3.model.ResponseSignVerifyParams;
import cn.felord.payment.wechat.v3.model.batchtransfer.CreateBatchTransferParams;
import cn.felord.payment.wechat.v3.model.batchtransfer.QueryBatchTransferDetailParams;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageCondition;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.law.domain.dto.LawOrderDTO;
import com.ruoyi.law.domain.entity.LawOrder;
import com.ruoyi.law.domain.entity.LawService;
import com.ruoyi.law.domain.entity.LawTeam;
import com.ruoyi.law.domain.query.LawOtherOrderQuery;
import com.ruoyi.law.domain.query.LawVipOrderQuery;
import com.ruoyi.law.enums.OrderState;
import com.ruoyi.law.enums.OrderType;
import com.ruoyi.law.service.*;
import com.ruoyi.law.utils.OrderUtil;
import com.ruoyi.law.utils.SmsUtil;
import com.ruoyi.law.utils.UserUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 律师订单 前端控制器
 * </p>
 *
 * @author code
 * @since 2022-11-23
 */
@Slf4j
@Api(tags = "订单功能")
@Validated
@RestController
@RequestMapping("/order")
public class LawOrderController extends BaseController {

    @Autowired
    private ILawOrderService orderService;
    @Autowired
    private ILawVipService vipService;
    @Autowired
    private ILawLawyerService lawyerService;
    @Autowired
    private ILawTeamService teamService;
    @Autowired
    private ILawServiceService serviceService;
    @Autowired
    private WechatApiProvider wechatApiProvider;

    @Value("${wechat.pay.v3.miniApp.app-id}")
    private String appid;

    @ApiOperation("订单列表")
    @GetMapping("/list")
    public R<Page<LawOrderDTO>> list(PageCondition<LawOrderDTO> pageCondition, LawOrderDTO lawOrderDTO) {
        Page<LawOrderDTO> page = orderService.myPage(pageCondition.toMyPage(), lawOrderDTO);
        return R.ok(page);
    }

    @RepeatSubmit
    @ApiOperation("生成vip订单")
    @PostMapping("/generateVipOrder")
    public R<ObjectNode> generateVipOrder(@Validated @RequestBody LawVipOrderQuery vipOrderQuery) {
        // 生成订单后 返回前端微信支付需要的参数
        WechatResponseEntity<ObjectNode> prePara = orderService.generateVipOrder(vipOrderQuery);
        return R.ok(prePara.getBody());
    }

    @RepeatSubmit
    @ApiOperation("生成咨询或服务订单")
    @PostMapping("/generateOtherOrder")
    public R<ObjectNode> generateOtherOrder(@Validated @RequestBody LawOtherOrderQuery otherOrderQuery) {
        // 生成订单后 返回前端微信支付需要的参数
        WechatResponseEntity<ObjectNode> prePara = orderService.generateOtherOrder(otherOrderQuery);
        return R.ok(prePara == null ? null : prePara.getBody());
    }

    @RepeatSubmit
    @ApiOperation("生成文书生成订单")
    @GetMapping("/generateFileOrder")
    public R<Map<String, Object>> generateFileOrder(@Validated @NotNull(message = "金额不能为空") BigDecimal price) {
        // 生成订单后 返回前端微信支付需要的参数
        Map<String, Object> map = orderService.generateFileOrder(price);
        return R.ok(map);
    }

    @RepeatSubmit
    @ApiOperation("根据订单id支付")
    @GetMapping("/payOrder")
    public R<ObjectNode> payOrder(@NotNull(message = "订单id不能为空") Long orderId) {
        // 生成订单后 返回前端微信支付需要的参数
        WechatResponseEntity<ObjectNode> prePara = orderService.payOrder(orderId);
        return R.ok(prePara.getBody());
    }

    @ApiOperation("线下支付确认支付")
    @GetMapping("/confirmPayment")
    public R<Object> confirmPayment(Long orderId) {
        LawOrder byId = orderService.getById(orderId);
        Assert.notNull(byId, "订单不存在");
        byId.setState(OrderState.paid.getValue());
        return R.ok();
    }

    @ApiOperation("根据订单号查询订单情况")
    @GetMapping("/queryOrders")
    public R<Map<String, Object>> queryOrders(@NotBlank(message = "订单号不能为空") String orderNum) {
        Map<String, Object> res = orderService.queryOrders(orderNum);
        return R.ok(res);
    }

    @ApiOperation("选择律师(团队)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderId", value = "订单id", required = true),
            @ApiImplicitParam(name = "teamId", value = "律师团队id", required = true),
    })
    @GetMapping("/chooseLawyer")
    public R<Object> chooseLawyer(@NotNull(message = "订单id不能为空") Long orderId,
                                  @NotNull(message = "律师团队id不能为空") Long teamId) {
        LambdaUpdateWrapper<LawOrder> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(LawOrder::getId, orderId)
                .set(LawOrder::getLawyerId, teamId);
        orderService.update(updateWrapper);
        // 分配承办人后发送短信
        LawOrder lawOrder = orderService.getById(orderId);
        String orderType = lawOrder.getOrderType();
        String orderName = OrderType.getName(orderType);
        Long uid = lawOrder.getUid();
        SysUser user = UserUtil.getUser(uid);
        String nickName = user.getNickName();
        // 真实姓名
        String remark = user.getRemark();
        String userName = StrUtil.isBlank(remark) ? nickName : remark;
        // 查询律师相关信息
        LawTeam lawTeam = teamService.getById(teamId);
        Long teamUserId = lawTeam.getUserId();
        SysUser teamUser = UserUtil.getUser(teamUserId);

        Long consultingId = lawOrder.getConsultingId();
        LawService lawService = serviceService.getById(consultingId);
        if (OrderType.consultingOrder.getType().equals(orderType)) {
            // 咨询订单
            try {
                // 分配律师后通知用户
                SmsUtil.send2(user.getPhonenumber(), teamUser.getPhonenumber());
                // 分配律师后通知律师
                SmsUtil.send4(teamUser.getPhonenumber(), userName, lawService.getTitle(), user.getPhonenumber());
            } catch (Exception e) {
                log.error("发送短信失败", e);
            }
        } else if (OrderType.serviceOrder.getType().equals(orderType)) {
            // 服务订单
            try {
                // 分配律师后通知律师
                SmsUtil.send3(teamUser.getPhonenumber(), userName, lawService.getTitle());
                // 分配律师后通知用户
                SmsUtil.send5(user.getPhonenumber());
            } catch (Exception e) {
                log.error("发送短信失败", e);
            }
        }
        return R.ok();
    }

    @ApiOperation("追加金额")
    @GetMapping("/addAmount")
    public R<Object> addAmount(@NotNull(message = "订单id不能为空") Long orderId,
                               @NotNull(message = "金额不能为空") BigDecimal amount) {
        LawOrder lawOrder = orderService.getById(orderId);
        BigDecimal addAmount = lawOrder.getPrice().add(amount);
        LambdaUpdateWrapper<LawOrder> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(LawOrder::getId, orderId).set(LawOrder::getPrice, addAmount);
        orderService.update(updateWrapper);
        return R.ok();
    }

    @ApiOperation("补充资料")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderId", value = "订单id", required = true),
            @ApiImplicitParam(name = "supplement", value = "资料"),
            @ApiImplicitParam(name = "file", value = "文件（逗号分割）")
    })
    @GetMapping("/addSupplement")
    public R<Object> addSupplement(@NotNull(message = "订单id不能为空") Long orderId, String supplement, String file) {
        LambdaUpdateWrapper<LawOrder> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(LawOrder::getId, orderId)
                .set(LawOrder::getSupplement, supplement)
                .set(LawOrder::getFile, file);
        boolean update = orderService.update(updateWrapper);
        return update ? R.ok() : R.fail("补充资料失败");
    }

    @ApiOperation("修改律师的提成比例")
    @GetMapping("/changeRatio")
    public R<Object> changeRatio(@NotNull(message = "订单id不能为空") Long id,
                                 @NotNull(message = "提成比例不能为空") Integer ratio) {
        orderService.changeRatio(id, ratio);
        return R.ok();
    }

    @ApiOperation("关闭订单")
    @GetMapping("/closeOrder")
    public R<Object> closeOrder(@NotNull(message = "订单id不能为空") Long id) {
        orderService.closeOrder(id);
        return R.ok();
    }

    @ApiOperation("详情")
    @GetMapping("/info")
    public R<LawOrder> info(@NotNull(message = "订单id不能为空") Long id) {
        LawOrder lawOrder = orderService.getById(id);
        return R.ok(lawOrder);
    }

    /**
     * 微信支付成功回调.
     * <p>
     * 无需开发者判断，只有扣款成功微信才会回调此接口
     *
     * @param wechatpaySerial    the wechatpay serial
     * @param wechatpaySignature the wechatpay signature
     * @param wechatpayTimestamp the wechatpay timestamp
     * @param wechatpayNonce     the wechatpay nonce
     * @param request            the request
     * @return the map
     */
    @Anonymous
    @SneakyThrows
    @PostMapping("/transaction")
    public Map<String, ?> transactionCallback(
            @RequestHeader("Wechatpay-Serial") String wechatpaySerial,
            @RequestHeader("Wechatpay-Signature") String wechatpaySignature,
            @RequestHeader("Wechatpay-Timestamp") String wechatpayTimestamp,
            @RequestHeader("Wechatpay-Nonce") String wechatpayNonce,
            HttpServletRequest request) {
        String body = request.getReader().lines().collect(Collectors.joining());
        log.info("微信支付回调{}", body);
        // 对请求头进行验签 以确保是微信服务器的调用
        ResponseSignVerifyParams params = new ResponseSignVerifyParams();
        params.setWechatpaySerial(wechatpaySerial);
        params.setWechatpaySignature(wechatpaySignature);
        params.setWechatpayTimestamp(wechatpayTimestamp);
        params.setWechatpayNonce(wechatpayNonce);
        params.setBody(body);
        return wechatApiProvider.callback("miniApp").transactionCallback(params, data -> {
            // 对回调解析的结果进行消费
            log.info("transactionCallback: {}", data);
            String outTradeNo = data.getOutTradeNo();
            TradeState tradeState = data.getTradeState();
            if (TradeState.SUCCESS.equals(tradeState)) {
                LawOrder order = orderService.getByOrderNum(outTradeNo);
                // 状态为未支付时修改为已支付
                if (StrUtil.equals(order.getState(), OrderState.notPaid.getValue())) {
                    orderService.updateOrder(order);
                }
            }
        });
    }


    @ApiOperation("test1")
    @GetMapping("/test1")
    public R test1() {
        WechatBatchTransferApi miniApp = wechatApiProvider.batchTransferApi("miniApp");

        CreateBatchTransferParams transferParams = new CreateBatchTransferParams();
        transferParams.setAppid(appid);
        transferParams.setOutBatchNo(OrderUtil.getOrderNum(SecurityUtils.getUserId()));
        log.info("outBatchNo:{}", transferParams.getOutBatchNo());
        transferParams.setBatchName("测试");
        transferParams.setBatchRemark("测试");
        CreateBatchTransferParams.TransferDetailListItem transferDetailListItem =
                new CreateBatchTransferParams.TransferDetailListItem();
        transferDetailListItem.setOutDetailNo(OrderUtil.getOrderNum(SecurityUtils.getUserId()));
        log.info("outDetailNo:{}", transferDetailListItem.getOutDetailNo());
        transferDetailListItem.setTransferAmount(100);
        transferDetailListItem.setTransferRemark("测试");
        transferDetailListItem.setOpenid(SecurityUtils.getLoginUser().getUser().getOpenid());
        transferDetailListItem.setUserName("李毅");
        transferParams.setTransferDetailList(Collections.singletonList(transferDetailListItem));
        transferParams.setTotalAmount(100);
        transferParams.setTotalNum(1);

        WechatResponseEntity<ObjectNode> responseEntity = miniApp.batchTransfer(transferParams);
        log.info("responseEntity:{}", responseEntity);
        return R.ok(responseEntity);
    }

    @ApiOperation("test2")
    @GetMapping("/test2")
    public R test2(String outBatchNo, String outDetailNo) {
        WechatBatchTransferApi miniApp = wechatApiProvider.batchTransferApi("miniApp");

        QueryBatchTransferDetailParams detailParams = new QueryBatchTransferDetailParams();
        detailParams.setBatchIdOrOutBatchNo(outBatchNo);
        detailParams.setDetailIdOrOutDetailNo(outDetailNo);
        WechatResponseEntity<ObjectNode> objectNodeWechatResponseEntity = miniApp.queryBatchDetailByMch(detailParams);

        return R.ok(objectNodeWechatResponseEntity);
    }

}
